#include "ShadowMapFBO.hpp"
#include "../HDRDemoConstants.hpp"
#include <assert.h>
#include "../Globals.hpp"

ShadowMapFBO::ShadowMapFBO()
{
	//! Set all things necessary to successfuly render shadow map
	SetShadowMapFBO();
}

ShadowMapFBO::~ShadowMapFBO()
{
	//! Delete framebuffer and renderbuffer
	ExtensionsLoader::glDeleteFramebuffersEXT( 1, &m_frameBufferObject );
	ExtensionsLoader::glDeleteRenderbuffersEXT( 1, &m_depthBuffer );

	//! Delete shadow map texture from VRAM
	glDeleteTextures( 1, &m_shadowMap );
}

void ShadowMapFBO::RenderToFBO(bool isTargetFBO)
{
	if( isTargetFBO )
	{
		//! Bind FBO - depth buffer will be rendered as a texture
		ExtensionsLoader::glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frameBufferObject );
		ExtensionsLoader::glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, *(Globals::GetInstance()->GetSpecialTexture( SHADOW_MAP)), 0 );
		ExtensionsLoader::glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_renderBuffer );
		

		glPushAttrib(GL_VIEWPORT_BIT);
		glViewport(0, 0, 1024, 1024);

		glClearColor(1.0f, 1.0f, 1.0f, 1.0f);

		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	}
	else
	{
		//! Turn off FBO and render in standard mode
		glPopAttrib();
		ExtensionsLoader::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
	}
}

bool ShadowMapFBO::SetShadowMapFBO()
{
	ExtensionsLoader::glGenFramebuffersEXT( 1, &m_frameBufferObject );
	ExtensionsLoader::glGenRenderbuffersEXT( 1, &m_renderBuffer );

	ExtensionsLoader::glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_renderBuffer );
	ExtensionsLoader::glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, 4096, 4096 );

	IsShadowMapFBOOK();

	return true;
}

bool ShadowMapFBO::IsShadowMapFBOOK() const
{
	// Check for errors
    GLenum status;                                            
    status = ExtensionsLoader::glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT ); 
    switch( status ) 
	{                                          
      case GL_FRAMEBUFFER_COMPLETE_EXT:                       
        break;                                                
      case GL_FRAMEBUFFER_UNSUPPORTED_EXT:                    
        /* choose different formats */                        
        break;                                                
      default:                                                
        /* programming error; will fail on all hardware */    
        assert( 0 );                                            
    }

	return true;
}

GLuint ShadowMapFBO::GetShadowMapID() const
{
	return m_shadowMap;
}